package com.shanshui.fragmentback;

import androidx.activity.OnBackPressedCallback;
import androidx.activity.OnBackPressedDispatcher;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleEventObserver;
import androidx.lifecycle.LifecycleOwner;

import java.util.ArrayDeque;
import java.util.Iterator;

/**
 * @author mashanshui
 * @date 2021/12/24
 * @desc TODO
 */
public class OnBackPressedDispatcherV2 {
    private Runnable mFallbackOnBackPressed;

    ArrayDeque<OnBackPressedCallbackV2> mBackArray = new ArrayDeque<>();

    public OnBackPressedDispatcherV2(Runnable mFallbackOnBackPressed) {
        this.mFallbackOnBackPressed = mFallbackOnBackPressed;
    }

    public OnBackPressedCancellable addBack(OnBackPressedCallbackV2 onBackPressedCallbackV2) {
        OnBackPressedCancellable onBackPressedCancellable = new OnBackPressedCancellable(onBackPressedCallbackV2);
        onBackPressedCallbackV2.setCancellable(onBackPressedCancellable);
        mBackArray.add(onBackPressedCallbackV2);
        return onBackPressedCancellable;
    }

    public void addBack(@NonNull LifecycleOwner owner,
                            @NonNull OnBackPressedCallbackV2 onBackPressedCallback) {
        Lifecycle lifecycle = owner.getLifecycle();
        if (lifecycle.getCurrentState() == Lifecycle.State.DESTROYED) {
            return;
        }
        onBackPressedCallback.setCancellable(
                new LifecycleOnBackPressedCancellable(lifecycle, onBackPressedCallback));
    }

    public void removeBack(OnBackPressedCallbackV2 onBackPressedCallbackV2) {
        mBackArray.remove(onBackPressedCallbackV2);
    }

    public void onBackPressed() {
        Iterator<OnBackPressedCallbackV2> onBackPressedCallbackV2Iterator = mBackArray.descendingIterator();
        while (onBackPressedCallbackV2Iterator.hasNext()) {
            if (onBackPressedCallbackV2Iterator.next().handlerBackPress()) {
                return;
            }
        }
        mFallbackOnBackPressed.run();
    }

    private class OnBackPressedCancellable implements Cancellable {
        private OnBackPressedCallbackV2 onBackPressedCallbackV2;

        public OnBackPressedCancellable(OnBackPressedCallbackV2 onBackPressedCallbackV2) {
            this.onBackPressedCallbackV2 = onBackPressedCallbackV2;
        }

        @Override
        public void cancel() {
            removeBack(onBackPressedCallbackV2);
        }
    }

    private class LifecycleOnBackPressedCancellable implements Cancellable, LifecycleEventObserver {
        private final Lifecycle mLifecycle;
        private OnBackPressedCallbackV2 onBackPressedCallbackV2;
        private Cancellable mCurrentCancellable;

        public LifecycleOnBackPressedCancellable(Lifecycle mLifecycle, OnBackPressedCallbackV2 onBackPressedCallbackV2) {
            this.mLifecycle = mLifecycle;
            this.onBackPressedCallbackV2 = onBackPressedCallbackV2;
            mLifecycle.addObserver(this);
        }

        @Override
        public void cancel() {
            mLifecycle.removeObserver(this);
            removeBack(onBackPressedCallbackV2);
        }

        @Override
        public void onStateChanged(@NonNull LifecycleOwner source, @NonNull Lifecycle.Event event) {
            if (event == Lifecycle.Event.ON_START) {
                mCurrentCancellable = addBack(onBackPressedCallbackV2);
            } else if (event == Lifecycle.Event.ON_STOP) {
                mCurrentCancellable.cancel();
            } else if (event == Lifecycle.Event.ON_DESTROY) {
                cancel();
            }
        }
    }

} 
